﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Windows.Threading;



namespace MapTool
{
    public partial class MapViewModel : ObservableRecipient
    {
        [ObservableProperty]
        private WriteableBitmap? _wBitmap;
        [ObservableProperty]
        private WriteableBitmap? _wBitmap2= new WriteableBitmap(1000, 1000, 96, 96, PixelFormats.Pbgra32, null);
        //一个组合变换容器
        [ObservableProperty]
        private TransformGroup? _transformGroup;
        //实现二维平移（位移）效果的变换
        private TranslateTransform? _translateTransform;
        //实现缩放功能
        private ScaleTransform? _scaleTransform;
        [ObservableProperty]
        private TextBlock? _textBlock;
        private ContextMenu contextMenu = new ContextMenu();
        private Rectangle? _selectVisual;
        private Point _startPoint;
        [ObservableProperty]
        private PointId lastSelectPointId = new PointId();

        public MapWafer Map { get; set; } = new MapWafer();
        public MapViewModel()
        {
            if (Map == null) { Map = new MapWafer(); }
        }

        //初始化图像格式相关
        [RelayCommand]
        private void InitializeBit()
        {
            int X = Map!.OneDiePix_X;
            int Y = Map!.OneDiePix_Y;
            int Xx = Map!.OneCutRoadPix_X;
            int Yy = Map!.OneCutRoadPix_Y;
            Map!.ImageWidth = (X + Xx) * Map!.DieCount_X;
            Map!.ImageHeight = (Y + Yy) * Map!.DieCount_Y;
            if (Map!.ImageWidth <= 0 || Map!.ImageHeight <= 0)
            {
                return;
            }
            WBitmap = new WriteableBitmap(Map!.ImageWidth, Map!.ImageHeight, 96, 96, PixelFormats.Pbgra32, null);
            _scaleTransform = new ScaleTransform();
            _translateTransform = new TranslateTransform();
            TransformGroup = new TransformGroup();
            TransformGroup.Children.Add(_scaleTransform);
            TransformGroup.Children.Add(_translateTransform);
            if (Map!.Pixels != null && Map!.Pixels.Count() != 0)
            {
                WriteBytes();
            }
        }
        //读Map文件
        [RelayCommand]
        private void ReadMapFile()
        {
            string filePath = "";
            Microsoft.Win32.OpenFileDialog openFileDialog = new();
            openFileDialog.Multiselect = true;//该值确定是否可以选择多个文件
            openFileDialog.Title = "请选择文件";
            openFileDialog.Filter = "txt格式（*.txt）|*.txt|所有文件|*.*";
            if (openFileDialog.ShowDialog() == true)
            {
                filePath = openFileDialog.FileName;
            }
            else
            {
                return;
            }
            Map!.MapReadString = new List<string>();      
            try
            {
                using (StreamReader reader = new StreamReader(filePath))
                {
                    string line; int lineY = 0;
                    while ((line = reader.ReadLine()!) != null)
                    {
                        line = line.Trim().Split(":").Last().Replace("___", ".").Replace("000", "1").Replace("012", "1").Replace("@@@", "1").Replace(" ", "");
                        Map!.MapReadString.Add(line);
                        Map.DieCount_X = line.Length;   
                        lineY += 1;
                    }
                    Map.DieCount_Y = lineY;
                    Map!.XYPoints = new PointId[Map.DieCount_X, Map.DieCount_Y];
                    for (int i = 0; i < Map.DieCount_Y; i++)
                    {
                        for (int j = 0; j < Map.DieCount_X; j++)
                        {                      
                            char c = Map!.MapReadString[i][j];
                            PointId pointId = new PointId() { X = j, Y = i, Key = c.ToString() };
                            Map!.XYPoints[j,i]= pointId;
                            if (!Map!.RulekeysItem!.Any(p => p == c.ToString()))
                            {
                                Map!.RulekeysItem!.Add(c.ToString());
                            }
                        }             
                    }
                }
            }
            catch (Exception ex)
            {
            }
            return;
        }

        //图像数据写入到图片
        private void WriteBytes()
        {
            if (WBitmap == null) return;
            Int32Rect rect = new Int32Rect(0, 0, WBitmap.PixelWidth, WBitmap.PixelHeight);
            WBitmap.WritePixels(rect, Map!?.Pixels, WBitmap.PixelWidth * 4, 0);
        }
        //绘制图片
        [RelayCommand]
        private void DrawMapByPara()
        {
            Stopwatch sw = new Stopwatch();
            sw.Restart();

            // 缓存WriteableBitmap属性，避免重复访问
            int width = WBitmap!.PixelWidth;
            int height = WBitmap.PixelHeight;
            int stride = width * 4; // 每行字节数

            // 缓存Map属性，避免重复访问
            int oneCutRoadPixX = Map.OneCutRoadPix_X;
            int oneCutRoadPixY = Map.OneCutRoadPix_Y;
            int oneDiePixX = Map.OneDiePix_X;
            int oneDiePixY = Map.OneDiePix_Y;
            Color cutRoadColor = Map.CutRoadColor.S2Color();
            PointId[,] xyPoints = Map.XYPoints;
            int cellWidth = oneCutRoadPixX + oneDiePixX;
            int cellHeight = oneCutRoadPixY + oneDiePixY;

            // 预计算规则映射：Key -> Color
            var keyToColorMap = new Dictionary<string, Color>();
            foreach (var rule in Map.Rules)
            {
                keyToColorMap[rule.Key] = rule.SetColor;
            }

            // 获取像素数据
            Int32Rect rect = new Int32Rect(0, 0, width, height);
            byte[] pixels = new byte[width * height * 4];
            WBitmap.CopyPixels(rect, pixels, stride, 0);

            // 并行处理行（利用多核CPU，大幅提升性能）
            Parallel.For(0, height, y =>
            {
                // 计算当前行所属的单元格索引和相对位置
                int cellY = y / cellHeight;
                int relY = y % cellHeight;
                bool isCutRoadY = relY < oneCutRoadPixY;

                int rowOffset = y * width * 4; // 当前行的起始偏移量

                for (int x = 0; x < width; x++)
                {
                    int index = rowOffset + x * 4; // 优化：直接计算索引，避免重复乘法

                    // 计算当前列所属的单元格索引和相对位置
                    int cellX = x / cellWidth;
                    int relX = x % cellWidth;
                    bool isCutRoadX = relX < oneCutRoadPixX;

                    // 切割道判断（优化逻辑表达式）
                    if (isCutRoadX || isCutRoadY)
                    {
                        pixels[index + 0] = cutRoadColor.B;
                        pixels[index + 1] = cutRoadColor.G;
                        pixels[index + 2] = cutRoadColor.R;
                        pixels[index + 3] = cutRoadColor.A;
                    }
                    else
                    {
                        // 获取当前单元格的PointId（添加边界检查，防止越界）
                        if (cellX < xyPoints.GetLength(0) && cellY < xyPoints.GetLength(1))
                        {
                            PointId point = xyPoints[cellX, cellY];

                            // 使用预计算的映射表查找颜色
                            if (keyToColorMap.TryGetValue(point.Key, out Color color))
                            {
                                pixels[index + 0] = color.B;
                                pixels[index + 1] = color.G;
                                pixels[index + 2] = color.R;
                                pixels[index + 3] = color.A;
                            }
                            else
                            {
                                // 默认颜色（透明黑色）
                                pixels[index + 0] = 0;
                                pixels[index + 1] = 0;
                                pixels[index + 2] = 0;
                                pixels[index + 3] = 255;
                            }
                        }
                        else
                        {
                            // 越界处理（使用切割道颜色）
                            pixels[index + 0] = cutRoadColor.B;
                            pixels[index + 1] = cutRoadColor.G;
                            pixels[index + 2] = cutRoadColor.R;
                            pixels[index + 3] = cutRoadColor.A;
                        }
                    }
                }
            });

            // 将修改后的像素数据写回到WriteableBitmap
            WBitmap.WritePixels(rect, pixels, stride, 0);

            sw.Stop();
            Debug.WriteLine($"绘图耗时: {sw.ElapsedMilliseconds}ms");
        }
    
        private byte[] GetBytes()
        {
            if (WBitmap == null) return new byte[0];
            Int32Rect rect = new Int32Rect(0, 0, WBitmap.PixelWidth, WBitmap.PixelHeight);
            byte[] pixels = new byte[WBitmap.PixelWidth * WBitmap.PixelHeight * 4];
            WBitmap.CopyPixels(rect, pixels, WBitmap.PixelWidth * 4, 0);
            return pixels;
        }
        //重新创建Map
        [RelayCommand]
        private void ReCreateMap()
        {        
            InitializeBit();
            DrawMapByPara();
            RefreshRules();
        }
        //重新创建规则
        [RelayCommand]
        private void ReCreateRules()
        {
            Map!.Rules = new ObservableCollection<Rules>();
            List<Color> colors = new List<Color>();
            int count = Map!.RulekeysItem!.Count();
            colors = DistinctColorGenerator.GenerateDistinctColors(count);
            for (int i = 0; i < count; i++)
            {
                Map!.Rules.Add(new Rules(ResultEnum.Unknown, Map!.RulekeysItem![i], colors[i]));
            }
        }
        //添加一个规则
        [RelayCommand]
        private void AddOneRule()
        {
            if (Map!.Rules != null)
            {
                Map!.Rules.Add(new Rules(ResultEnum.Unknown, "."));
            }
        }
        //删除规则
        [RelayCommand]
        private void RemoveRule(ListView lstView)
        {
            if (lstView.SelectedItems != null)
            {
                // 先收集要删除的项目，再删除
                var rulesToRemove = new List<Rules>();
                foreach (var rule in lstView.SelectedItems)
                {
                    if (rule is Rules ru)
                    {
                        rulesToRemove.Add(ru);
                    }
                }
                // 安全移除
                foreach (var rule in rulesToRemove)
                {
                    Map!.Rules!.Remove(rule);
                }
            }
        }
        //设置选中颜色
        private void SetSelectColor(PointId point, Color color)
        {
            if (point == null) return;

            if (WBitmap == null) return;
            int _imageWidth = Map!.ImageWidth;
            int _imageHeight = Map!.ImageHeight;

            int _gridWidth = (int)((Map!.OneDiePix_X + Map!.OneCutRoadPix_X));
            int _gridHeight = (int)((Map!.OneDiePix_Y + Map!.OneCutRoadPix_Y));

            Int32Rect rect = new Int32Rect(0, 0, _imageWidth, _imageHeight);
            byte[] pixels = new byte[_imageWidth * _imageHeight * 4]; // 4 bytes per pixel for Pbgra32 format
            WBitmap.CopyPixels(rect, pixels, _imageWidth * 4, 0);

            //1.计算startPoint点所处网格左上角的点
            var startInx = (int)point.X * _gridWidth;
            var startIny = (int)point.Y * _gridHeight;
            //2.计算EndPoint点所处网格的右下角的点

            // 修改像素数据来绘制网格
            for (int y = 0; y < Map!.OneDiePix_Y + Map!.OneCutRoadPix_Y * 2; y++)
            {
                for (int x = 0; x < Map!.OneDiePix_X + Map!.OneCutRoadPix_X * 2; x++)
                {
                    int index = (startIny * _imageWidth * 4) + ((startInx + x) * 4) + (y * _imageWidth * 4);
                    if (index + 4 > pixels.Length) break;

                    pixels[index + 0] = color.B;
                    pixels[index + 1] = color.G;
                    pixels[index + 2] = color.R;
                    pixels[index + 3] = color.A;
                }
            }
            WBitmap.WritePixels(rect, pixels, _imageWidth * 4, 0);
        }
        //恢复选中颜色
        private void RecoverSelectColor(PointId point, Color color)
        {
            if (point == null || WBitmap == null || Map == null) return;

            // 获取必要参数
            int width = Map.ImageWidth;
            int height = Map.ImageHeight;
            int gridWidth = Map.OneDiePix_X + Map.OneCutRoadPix_X;
            int gridHeight = Map.OneDiePix_Y + Map.OneCutRoadPix_Y;
            int borderWidth = Map.OneCutRoadPix_X * 2;
            int borderHeight = Map.OneCutRoadPix_Y * 2;

            // 准备像素缓冲区
            var rect = new Int32Rect(0, 0, width, height);
            byte[] pixels = new byte[width * height * 4];
            WBitmap.CopyPixels(rect, pixels, width * 4, 0);

            // 计算起始坐标
            int startX = (int)point.X * gridWidth;
            int startY = (int)point.Y * gridHeight;

            // 绘制外层边框
            for (int y = 0; y < Map.OneDiePix_Y + borderHeight; y++)
            {
                int pixelY = startY + y;
                for (int x = 0; x < Map.OneDiePix_X + borderWidth; x++)
                {
                    // 跳过内部区域（留给后续填充）
                    bool isInnerRegion =
                        x >= Map.OneCutRoadPix_X &&
                        x < (Map.OneCutRoadPix_X + Map.OneDiePix_X) &&
                        y >= Map.OneCutRoadPix_Y &&
                        y < (Map.OneCutRoadPix_Y + Map.OneDiePix_Y);

                    if (isInnerRegion) continue;
                    int pixelX = startX + x;
                    Color clr = new Color();
                    clr.B = Map.CutRoadColor.B;
                    clr.G = Map.CutRoadColor.G;
                    clr.R = Map.CutRoadColor.R;
                    clr.A = Map.CutRoadColor.A;
                    SetPixel(pixels, width, pixelX, pixelY, clr);
                }
            }

            // 填充内部区域
            for (int y = Map.OneCutRoadPix_Y; y < Map.OneCutRoadPix_Y + Map.OneDiePix_Y; y++)
            {
                int pixelY = startY + y;
                for (int x = Map.OneCutRoadPix_X; x < Map.OneCutRoadPix_X + Map.OneDiePix_X; x++)
                {
                    int pixelX = startX + x;
                    SetPixel(pixels, width, pixelX, pixelY, color);
                }
            }

            WBitmap.WritePixels(rect, pixels, width * 4, 0);

            // 局部函数：设置单个像素颜色
            void SetPixel(byte[] buffer, int imgWidth, int x, int y, Color clr)
            {
                if (x >= imgWidth || y >= height || x < 0 || y < 0) return;
                int index = (y * imgWidth + x) * 4;
                buffer[index] = clr.B;
                buffer[index + 1] = clr.G;
                buffer[index + 2] = clr.R;
                buffer[index + 3] = clr.A;
            }
        }
        [RelayCommand]
        private void MouseMove(MouseEventArgs e)
        {
            Point tempPoint;
            if (e?.Source is IInputElement element)
            {
                tempPoint = e.GetPosition(element);
            }
            else
            {
                return;
            }
            int dieX_Select = (int)(tempPoint.X / (Map!.OneDiePix_X + Map!.OneCutRoadPix_X)) + Map!.DieOffsetCount_X;
            int dieY_Select = (int)(tempPoint.Y / (Map.OneDiePix_Y + Map!.OneCutRoadPix_Y)) + Map!.DieOffsetCount_Y;
            if (Map.Rules!.Any(P => P.Key == LastSelectPointId.Key))
            {
                Color color = Map.Rules!.First(P => P.Key == LastSelectPointId.Key).SetColor;
                RecoverSelectColor(LastSelectPointId, color);
            }
            PointId pointId = new PointId();

            pointId = Map!.XYPoints[dieX_Select, dieY_Select];
            if (Map.Rules!.Any(P => P.Key == pointId.Key))
            {
                Color color = Map.Rules!.First(P => P.Key == pointId.Key).SetColor;
                SetSelectColor(pointId, color);
                LastSelectPointId = pointId;
            }
            // _textBlock.Text = $"X:{dieX_Select:f0},Y:{dieY_Select:f0}\nResult:{pointId.Result}\nKey:{pointId.Key}";
        }
        [RelayCommand]
        private void MouseRightBtnDown(MouseEventArgs e)
        {
            Point tempPoint;
            if (e?.Source is IInputElement element)
            {
                tempPoint = e.GetPosition(element);
            }
            else
            {
                return;
            }
            int dieX_Select = (int)(tempPoint.X / (Map!.OneDiePix_X + Map!.OneCutRoadPix_X)) + Map!.DieOffsetCount_X;
            int dieY_Select = (int)(tempPoint.Y / (Map.OneDiePix_Y + Map!.OneCutRoadPix_Y)) + Map!.DieOffsetCount_Y;

        
                PointId pointId = new PointId();
                pointId = Map!.XYPoints[dieX_Select, dieY_Select];
                InitializeMenu(pointId);

                contextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.MousePoint;
                contextMenu.IsOpen = true;

                // 阻止事件继续冒泡
                e.Handled = true;
            
        }
        //保存结果到csv
        [RelayCommand]
        private void SaveToCsv()
        {
            string[] headers = { "X", "Y", "KEY", "Result" };
            // 创建保存文件对话框
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "CSV文件 (*.csv)|*.csv|所有文件 (*.*)|*.*";
            saveFileDialog.FilterIndex = 1;

            // 显示对话框
            if (saveFileDialog.ShowDialog() == true)
            {
                string filePath = saveFileDialog.FileName;

                // 写入数据到文件
                using (StreamWriter writer = new StreamWriter(filePath))
                {
                    // 写入标题行
                    writer.WriteLine(string.Join(",", headers));
                    // 写入数据行
                    foreach (var item in Map.XYPoints!)
                    {
                        string ss = item.X + "," + item.Y + "," + item.Key + "," + item.Result;
                        writer.WriteLine(ss);
                    }
                }

                MessageBox.Show("文件保存成功！", "成功", MessageBoxButton.OK, MessageBoxImage.Information);
            }
        }
        //保存结果到txt
        [RelayCommand]
        private void SaveToTxt()
        {
            // 创建保存文件对话框
            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Title = "保存文本文件",
                Filter = "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*",
                DefaultExt = ".txt",
                FileName = "点位数据.txt",
                OverwritePrompt = true,
                ValidateNames = true
            };

            // 显示对话框
            if (saveFileDialog.ShowDialog() == true)
            {
                string filePath = saveFileDialog.FileName;

                try
                {
                    //使用StringBuilder高效构建文本内容
                    StringBuilder contentBuilder = new StringBuilder();

                    for (int i = 0; i < Map.DieCount_Y; i++)
                    {
                        string ss = "";
                        for (int j = 0; j < Map.DieCount_X; j++)
                        {
                            int index = Map.DieCount_X * i + j;
                            ss += Map.XYPoints[j,i].Key;

                        }
                        contentBuilder.AppendLine(ss);
                    }

                    // 写入文件
                    File.WriteAllText(filePath, contentBuilder.ToString(), Encoding.UTF8);

                    MessageBox.Show($"文件已成功保存至:\n{filePath}",
                                   "保存成功",
                                   MessageBoxButton.OK,
                                   MessageBoxImage.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"保存文件时出错:\n{ex.Message}",
                                   "错误",
                                   MessageBoxButton.OK,
                                   MessageBoxImage.Error);
                }
            }
        }
        //保存结果到bmp
        [RelayCommand]
        private void SaveAsBmp()
        {
            if (WBitmap == null) return;
            // 创建保存文件对话框
            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Title = "保存为BMP文件",
                Filter = "BMP图像文件 (*.bmp)|*.bmp|所有文件 (*.*)|*.*",
                DefaultExt = ".bmp",
                FileName = $"图像_{DateTime.Now:yyyyMMdd_HHmmss}.bmp",
                OverwritePrompt = true
            };
            // 显示对话框
            if (saveFileDialog.ShowDialog() == true)
            {
                try
                {
                    if (WBitmap == null) throw new ArgumentNullException(nameof(WBitmap));
                    using (FileStream stream = new FileStream(saveFileDialog.FileName, FileMode.Create))
                    {
                        // 创建 BMP 编码器
                        BmpBitmapEncoder encoder = new BmpBitmapEncoder();

                        // 创建 BitmapFrame 并添加到编码器
                        BitmapFrame frame = BitmapFrame.Create(WBitmap);
                        encoder.Frames.Add(frame);

                        // 保存到文件流
                        encoder.Save(stream);
                    }
                    return;
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"保存失败: {ex.Message}", "错误",
                                   MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            return;
        }
        //保存结果到Jpg
        [RelayCommand]
        private void SaveAsJpg()
        {
            int quality = 90;
            if (WBitmap == null)
            {
                MessageBox.Show("无法保存：位图为空", "错误",
                               MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            // 创建保存文件对话框
            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Title = "保存为JPG图像",
                Filter = "JPEG图像文件 (*.jpg;*.jpeg)|*.jpg;*.jpeg|所有文件 (*.*)|*.*",
                DefaultExt = ".jpg",
                FileName = $"图像_{DateTime.Now:yyyyMMdd_HHmmss}",
                OverwritePrompt = true,
                AddExtension = true
            };

            // 显示对话框
            if (saveFileDialog.ShowDialog() != true) return;

            string filePath = saveFileDialog.FileName;

            try
            {

                // 确保质量在合理范围内
                quality = Math.Clamp(quality, 1, 100);

                using (FileStream stream = new FileStream(filePath, FileMode.Create))
                {
                    // 创建 JPG 编码器
                    JpegBitmapEncoder encoder = new JpegBitmapEncoder();

                    // 设置压缩质量
                    encoder.QualityLevel = quality;

                    // 创建 BitmapFrame 并添加到编码器
                    BitmapFrame frame = BitmapFrame.Create(WBitmap);
                    encoder.Frames.Add(frame);

                    // 保存到文件流
                    encoder.Save(stream);

                    // 显示成功消息
                    MessageBox.Show($"图像已成功保存至:\n{filePath}",
                               "保存成功",
                               MessageBoxButton.OK,
                               MessageBoxImage.Information);

                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存失败: {ex.Message}",
                               "错误",
                               MessageBoxButton.OK,
                               MessageBoxImage.Error);
                return;
            }
        }
        //刷新所有Die的规则
        private void RefreshRules()
        {
            foreach (var item in Map!.XYPoints!)
            {
                if (Map!.Rules!.Any(P => P.Key == item.Key))
                {
                    if (item.Result != Map!.Rules!.First(P => P.Key == item.Key).Result)
                    {
                        item.Result = Map!.Rules!.First(P => P.Key == item.Key).Result;

                    }

                    if (item.SetColor != Map!.Rules!.First(P => P.Key == item.Key).SetColor)
                    {
                        item.SetColor = Map!.Rules!.First(P => P.Key == item.Key).SetColor;
                    }
                }
            }
        }

        //初始化右键菜单
        private void InitializeMenu(PointId pointid)
        {
            contextMenu = new ContextMenu();
            for (int i = 0; i < Map!.RulekeysItem!.Count(); i++)
            {
                string newkey = Map!.RulekeysItem![i];
                AddMenuItem(contextMenu, Map!.RulekeysItem![i], () => MenuAction(pointid, newkey));
            }
        }
        //添加菜单
        private void AddMenuItem(ContextMenu menu, string header, Action action)
        {
            var menuItem = new MenuItem
            {
                Header = "修改结果→" + "\"" + header + "\"",
                Tag = header,
                Background = Brushes.Transparent,
                Foreground = Brushes.Black,
                BorderThickness = new Thickness(0),
                Padding = new Thickness(10, 5, 10, 5)
            };

            // 鼠标悬停效果
            menuItem.MouseEnter += (s, e) =>
            {
                ((MenuItem)s).Background = new SolidColorBrush(Color.FromArgb(30, 0, 0, 255));
            };

            menuItem.MouseLeave += (s, e) =>
            {
                ((MenuItem)s).Background = Brushes.Transparent;
            };

            // 点击事件
            menuItem.Click += (s, e) =>
            {
                action();
            };

            menu.Items.Add(menuItem);
        }
        //右键菜单绑定事件
        private void MenuAction(PointId pointId, string NewKey)
        {
            pointId.Key = NewKey;
            if (Map.Rules!.Any(P => P.Key == NewKey))
            {
                Map.XYPoints![pointId.X, pointId.Y].Result = Map.Rules!.First(P => P.Key == NewKey).Result;

                Color color = Map.Rules!.First(P => P.Key == NewKey).SetColor;

                RecoverSelectColor(pointId, color);
            }
            else
            {
                Map.XYPoints![pointId.X, pointId.Y].Result = ResultEnum.Unknown;
            }
        }
        //修改缩放比例
        [RelayCommand]
        private void ChaangeTransform(SelectionChangedEventArgs e)
        {
            if (e.Source is ComboBox cb)
            {
                double ScaleVal = Convert.ToDouble(cb.SelectedValue.ToString().Replace("%", "").ToString()) / 1000;


                if (ScaleVal < 0.01) ScaleVal = 0.01;

                if (_scaleTransform != null && _translateTransform != null)
                {
                    _scaleTransform!.ScaleX = ScaleVal;
                    _scaleTransform.ScaleY = ScaleVal;
                    _translateTransform!.X = 0;
                    _translateTransform.Y = 0;
                }

            }
        }

        //扫雷
        [RelayCommand]
        private void AreaMineSweeping()
        {
            PointId[,] pointIds= ProcessGridResult(Map!.XYPoints, Map.AreaMineSweepSize, Map.AreaMineSweepKey,Map.AreaMineSweepAllowCount);
            Map!.XYPoints= pointIds;
            DrawMapByPara();
            RefreshRules();

        }

        /// <summary>
        /// 处理二维字符数组，根据自定义范围和条件更新元素，  //数据处理扫雷模式，判断窗口内的结果
        /// </summary>
        /// <param name="input">原始二维字符数组</param>
        /// <param name="windowWidthHalf">检查范围半宽（如1=3列，2=5列）</param>
        /// <param name="windowHeightHalf">检查范围半高（如1=3行，2=5行）</param>
        /// <param name="targetChar">目标字符（如"9"）</param>
        /// <param name="thresholdCount">阈值数量（超过此数量则更新）</param>
        /// <returns>处理后的二维字符数组</returns>
        public PointId[,] ProcessGridResult( PointId[,] input,int windowSize,  string targetChar,int thresholdCount)
        {
            // 参数验证
            if (input == null)
            {
                MessageBox.Show("输入数据为空!");
                return input;
            }
            if (windowSize <= 0 || windowSize % 2 == 0)
            {
                MessageBox.Show("窗口大小必须为正奇数!");
                return input;
            }
            if (string.IsNullOrEmpty(targetChar))
            {
                MessageBox.Show("目标字符不能为空!");
                return input;
            }
            if (thresholdCount < 0)
            {
                MessageBox.Show("阈值数量不能为负数!");
                return input;
            }

            int rows = input.GetLength(0);
            int cols = input.GetLength(1);
            PointId[,] result = new PointId[rows, cols]; // 创建新数组，避免修改原数据


            // 复制原数据到结果数组（保留其他属性）
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    result[i, j] = input[i, j].Copy(); 
                }
            }

            // 计算半宽（例如窗口大小3 → 半宽1，窗口大小5 → 半宽2）
            int windowHalf = (windowSize - 1) / 2;

            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < cols; j++)
                {
                    // 计算3x3网格的边界
                    int startRow = Math.Max(0, i - windowHalf);
                    int endRow = Math.Min(rows - 1, i + windowHalf);
                    int startCol = Math.Max(0, j - windowHalf);
                    int endCol = Math.Min(cols - 1, j + windowHalf);

                    // 统计目标字符的数量
                    int targetCount = 0;
                    for (int r = startRow; r <= endRow; r++)
                    {
                        for (int c = startCol; c <= endCol; c++)
                        {
                            if (input[r, c].Key == targetChar)
                            {
                                targetCount++;
                            }
                        }
                    }

                    // 根据阈值判断是否更新当前元素
                    result[i, j].Key = targetCount >= thresholdCount ? targetChar : input[i, j].Key;
                }
            }

            return result;
        }

        //导入数据
        //添加一个规则
        [RelayCommand]
        private void AddOneMergingRule()
        {
            if (Map!.MergingRules != null)
            {
                Map!.MergingRules.Add(new MergingRule());
            }
        }
        //删除规则
        [RelayCommand]
        private void RemoveMergingRule(ListView lstView)
        {
            if (lstView.SelectedItems != null)
            {
                // 先收集要删除的项目，再删除
                var rulesToRemove = new List<MergingRule>();
                foreach (var rule in lstView.SelectedItems)
                {
                    if (rule is MergingRule ru)
                    {
                        rulesToRemove.Add(ru);
                    }
                }
                // 安全移除
                foreach (var rule in rulesToRemove)
                {
                    Map!.MergingRules!.Remove(rule);
                }
            }
        }

        private MapWafer  ReadMergeMapFileTXT()
        {

           MapWafer SourceMap= new MapWafer();
            string filePath = "";
            Microsoft.Win32.OpenFileDialog openFileDialog = new();
            openFileDialog.Multiselect = true;//该值确定是否可以选择多个文件
            openFileDialog.Title = "请选择文件";
            openFileDialog.Filter = "txt格式（*.txt）|*.txt|所有文件|*.*";
            if (openFileDialog.ShowDialog() == true)
            {
                filePath = openFileDialog.FileName;
            }
            else
            {
                return SourceMap;
            }
      
            try
            {
                using (StreamReader reader = new StreamReader(filePath))
                {
                    string line; int lineY = 0;
                    while ((line = reader.ReadLine()!) != null)
                    {
                        line = line.Trim().Split(":").Last().Replace("___", ".").Replace("000", "1").Replace("012", "1").Replace("@@@", "1").Replace(" ", "");
                        SourceMap!.MapReadString.Add(line);
                        SourceMap.DieCount_X = line.Length;
                        lineY += 1;
                    }
                    SourceMap.DieCount_Y = lineY;
                    SourceMap!.XYPoints = new PointId[SourceMap.DieCount_X, SourceMap.DieCount_Y];
                    for (int i = 0; i < SourceMap.DieCount_Y; i++)
                    {
                        for (int j = 0; j < SourceMap.DieCount_X; j++)
                        {
                            char c = SourceMap!.MapReadString[i][j];
                            PointId pointId = new PointId() { X = j, Y = i, Key = c.ToString() };
                            SourceMap!.XYPoints[j, i] = pointId;
                            if (!SourceMap!.RulekeysItem!.Any(p => p == c.ToString()))
                            {
                                SourceMap!.RulekeysItem!.Add(c.ToString());
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
            return SourceMap;
        }

        private MapWafer ReadMergeMapFileCSV()
        {
            MapWafer sourceMap = new MapWafer();
            Microsoft.Win32.OpenFileDialog openFileDialog = new();
            openFileDialog.Multiselect = true;
            openFileDialog.Title = "请选择文件";
            openFileDialog.Filter = "txt格式（*.csv）|*.csv|所有文件|*.*";

            if (openFileDialog.ShowDialog() != true)
                return sourceMap;

            try
            {
                var allPoints = new List<PointId>();
                Encoding encoding = Encoding.UTF8;

                // 处理多选文件
                foreach (string filePath in openFileDialog.FileNames)
                {
                    var lines = File.ReadAllLines(filePath, encoding);

                    for (int i = 1; i < lines.Length; i++)
                    {
                        if (string.IsNullOrWhiteSpace(lines[i]))
                            continue;

                        string[] ss = lines[i].Split(',');
                        PointId pp = new PointId
                        {
                            X = int.Parse(ss[0]),
                            Y = int.Parse(ss[1]),
                            Key = ss[2],
                            Result = (ResultEnum)Enum.Parse(typeof(ResultEnum), ss[3])
                        };
                        allPoints.Add(pp);
                    }
                }

                if (allPoints.Count == 0)
                    return sourceMap;

                // 计算X和Y的范围
                int minX = allPoints.Min(p => p.X);
                int maxX = allPoints.Max(p => p.X);
                int minY = allPoints.Min(p => p.Y);
                int maxY = allPoints.Max(p => p.Y);

                sourceMap.DieCount_X = maxX - minX + 1;
                sourceMap.DieCount_Y = maxY - minY + 1;

                // 创建查找表以O(1)时间复杂度访问点
                var pointLookup = new Dictionary<(int X, int Y), PointId>();
                foreach (var point in allPoints)
                {
                    pointLookup[(point.X, point.Y)] = point;
                }

                sourceMap.XYPoints = new PointId[sourceMap.DieCount_X, sourceMap.DieCount_Y];

                // 使用查找表填充数组
                for (int y = 0; y < sourceMap.DieCount_Y; y++)
                {
                    for (int x = 0; x < sourceMap.DieCount_X; x++)
                    {
                        int originalX = x ;
                        int originalY = y ;

                        if (pointLookup.TryGetValue((originalX, originalY), out PointId point))
                        {
                            sourceMap.XYPoints[x, y] = point;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // 实际项目中应该记录日志或显示错误信息
                Console.WriteLine($"读取文件时发生错误: {ex.Message}");
            }

            return sourceMap;
        }

        [RelayCommand]
        private void ReadMapFromCsv()
        {
            if (ReadMergeMapFileCSV().XYPoints==null )  return;
            DrawMapByPara();
            RefreshRules();
        }


        //合并Map
        [RelayCommand]
        private void MergeMapResult()
        {
            MapWafer SourceMap = ReadMergeMapFileTXT();

            if ( SourceMap.XYPoints == null ) return;
            if (SourceMap.XYPoints.Length != Map.XYPoints.Length)
            { 
            return;
            }
            for (int i = 0; i < Map!.DieCount_Y; i++)
            {
                for (int j = 0; j < Map!.DieCount_X; j++)
                {
                    if (Map!.XYPoints[j,i].Key!= SourceMap.XYPoints[j,i].Key)
                    {
                        foreach (var item in Map!.MergingRules!)
                        {
                            if ((item.SourceKey== SourceMap.XYPoints[j, i].Key )&&(Map!.XYPoints[j, i].Key==item.TargetKey))
                            {
                                Map!.XYPoints[j, i].Key = item.FinalKey;
                            }
                        }
                    }
                }
            }
            DrawMapByPara();
            RefreshRules();
        }

    }
}
